package 并发.多线程;

/**
 * 现有函数 printNumber 可以用一个整数参数调用，并输出该整数到控制台。
 * <p>
 * 例如，调用 printNumber(7) 将会输出 7 到控制台。
 * 给你类 ZeroEvenOdd 的一个实例，该类中有三个函数：zero、even 和 odd 。ZeroEvenOdd 的相同实例将会传递给三个不同线程：
 * <p>
 * 线程 A：调用 zero() ，只输出 0
 * 线程 B：调用 even() ，只输出偶数
 * 线程 C：调用 odd() ，只输出奇数
 * 修改给出的类，以输出序列 "010203040506..." ，其中序列的长度必须为 2n 。
 * <p>
 * 实现 ZeroEvenOdd 类：
 * <p>
 * ZeroEvenOdd(int n) 用数字 n 初始化对象，表示需要输出的数。
 * void zero(printNumber) 调用 printNumber 以输出一个 0 。
 * void even(printNumber) 调用printNumber 以输出偶数。
 * void odd(printNumber) 调用 printNumber 以输出奇数。
 * User: zhaixiaolong Date:2024/1/16 10:55 ProjectName: algorithm Version:
 */
public class 打印零与奇偶数 {


    class ZeroEvenOdd {
        private int n;

        boolean printZero = Boolean.FALSE;

        int printNum = 1;

        public ZeroEvenOdd(int n) {
            this.n = n;
        }


        public void zero() throws InterruptedException {
            synchronized (this) {
                while (printZero) {
                    wait();
                }
                if (printNum > n){
                    Thread.currentThread().stop();
                    return;
                }
                System.out.println("0");
                printZero = Boolean.TRUE;
                notify();
            }

        }

        public void even() throws InterruptedException {
            synchronized (this) {
                while (!printZero) {
                    wait();
                }
                while (printNum % 2 != 0) {
                    wait();
                }
                System.out.println(printNum);
                printNum++;
                printZero = Boolean.FALSE;
                notify();
            }

        }

        public void odd() throws InterruptedException {
            synchronized (this) {
                while (!printZero) {
                    wait();
                }
                while (printNum % 2 == 0) {
                    wait();
                }
                System.out.println(printNum);
                printNum++;
                printZero = Boolean.FALSE;
                notify();
            }

        }
    }

}
